package com.company.nuwa.common.domain;

import com.company.nuwa.common.enumration.IBizCode;
import com.company.nuwa.common.exception.BizException;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * All rights Reserved, Designed By Trump
 *
 * @version V1.0
 * @Description:
 * @author: Trump
 * @date: 2020/3/24
 * @Copyright: 2020 Trump Inc. All rights reserved.
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class HttpMessageResult<T> {

    private static final String DEFAULT_SUCCESS_MSG  = "success";

    private static final String DEFAULT_SUCCESS_OK   = "ok";

    private static final int    DEFAULT_SUCCESS_CODE = 200;

    private static final String DEFAULT_FAILURE_MSG  = "failure";

    private static final String DEFAULT_FAILURE_DATA = "fail";

    private static final int    DEFAULT_FAILURE_CODE = 500;

    private int                 code;

    private String              msg;

    private T                   data;

    private String              signature;

    private Header              header;

    public HttpMessageResult(int code, String msg, T data, String signature) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        this.signature = signature;
    }

    /**
     * 使用场景：一般为操作类，没有返回结果的情形
     *
     * @return
     */
    public static HttpMessageResult<String> success() {
        return success(DEFAULT_SUCCESS_OK);
    }

    /**
     * 默认成功的方法，开发中用的比较多
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> HttpMessageResult<T> success(T data) {
        return success(DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MSG, data);
    }

    /**
     * 全参数成功，定制化成功，开发中用的不多
     *
     * @param code
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    public static <T> HttpMessageResult<T> success(int code, String msg, T data) {
        return new HttpMessageResult<>(code, msg, data, null);
    }

    /**
     * 定制化错误：使用场景比较广泛
     *
     * @param code
     * @param msg
     * @return
     */
    public static <T> HttpMessageResult<T> failure(int code, String msg) {
        // 去除data放入默认字符串，如果feign接口本身声明了泛型且data不是String类型会引起反序列化失败，从而影响友好提示
        return new HttpMessageResult<>(code, msg, null, null);
    }

    /**
     * 定制化错误：使用场景比较广泛
     *
     * @param bizCode
     * @param <T>
     * @return
     */
    public static <T> HttpMessageResult<T> failure(IBizCode bizCode) {
        // 此处设置null，不放入固定字符串，便于调用方解析对接
        return new HttpMessageResult<>(bizCode.getCode(), bizCode.getMessage(), null, null);
    }

    /**
     * 判断是否执行成功
     *
     * @return
     */
    public Boolean isSuccess() {
        return this.getCode() == DEFAULT_SUCCESS_CODE;
    }

    /**
     * 若执行成功，则返回数据，否则抛业务异常
     * <p>
     * 在强业务流程中，建议使用该方式返回数据
     * <p>
     * e.g 操作数据
     *
     * @return
     */
    public T requireSuccessData() {
        if (isSuccess()) {
            return data;
        }
        throw new BizException(code, msg);
    }

    /**
     * 若执行失败，返回保底数据
     * <p>
     * 在弱业务流程中，建议使用该方式返回数据
     * <p>
     * e.g 查询数据
     *
     * @param defaultData
     * @return
     */
    public T defaultIfFailure(T defaultData) {
        if (isSuccess()) {
            return data;
        }
        return defaultData;
    }

    @Data
    public static final class Header {

        private long timestamp;

        private String traceId;

        private String uri;

        public static Header builder(String traceId, String uri){
            Header result = new Header();
            result.setTimestamp(System.currentTimeMillis());
            result.setTraceId(traceId);
            result.setUri(uri);
            return result;
        }
    }
}
